home *** CD-ROM | disk | FTP | other *** search
- #include "MSWindows.h"
-
- extern short gSound;
- extern WindowPtr gMineWindow;
- extern RGBColor gBlack,gWhite,gLtGray,gDkGray;
- extern PicHandle gPicts[];
-
- // Game Globals
- Rect gGameRect,
- gHdrRect,
- gFaceRect;
- Boolean gRunning,
- gMarks = false,
- gNewGame;
- gEndGame;
- short gFace;
-
- unsigned long gStartTime,now,then;
- short rows,cols,mines;
- unsigned char *pMineField = nil;
- unsigned char *pMineView = nil;
-
- short gGameType;
- short colrange[] = {12,16,30,16};
- short rowrange[] = {12,16,16,16};
- short minerange[] = {20,40,99,40};
-
- #pragma segment TheApp
- void
- NewGame(Boolean resize)
- {
- short r,c;
- Rect bounds;
-
- GetDateTime(&gStartTime);
- now = gStartTime;
- cols = colrange[gGameType];
- rows = rowrange[gGameType];
- mines = minerange[gGameType];
- if (pMineField) {
- DisposPtr(pMineField);
- DisposPtr(pMineView);
- }
- pMineField = NewPtrClear(rows*cols);
- pMineView = NewPtrClear(rows*cols);
- for (r = 0; r < rows; r++)
- for (c = 0; c < cols; c++)
- mineview(r,c) = kButtonPict;
- SetRect(&bounds,0,0,cols * kBox + 2*kBorder,rows * kBox + kHdrSize + kBorder);
- gHdrRect = bounds;
- gHdrRect.top = kBorderTop; // skip MSWindow Hdr
- gHdrRect.bottom = kHdrSize;
- gFaceRect.top = kBorderTop + kInsetLCD;
- gFaceRect.bottom = gFaceRect.top + kIconSize;
- gFaceRect.left = (gHdrRect.right - kIconSize) / 2;
- gFaceRect.right = gFaceRect.left + kIconSize;
- gFace = kHappyFace;
- gNewGame = true;
- gEndGame = false;
- gRunning = false;
- SetPort(gMineWindow);
- CreateGWorld(&bounds);
- SizeWindow((WindowPtr)gMineWindow,bounds.right,bounds.bottom,true); // fUpdate
- ((MSWindowPtr)gMineWindow)->child->portRect = gMineWindow->portRect;
- SizeMSWindow(((MSWindowPtr)gMineWindow)->child);
- ClipRect(&bounds);
- if (resize)
- EraseRect(&bounds);
- InvalRect(&bounds); // force an update now
- }
-
-
- void
- InitGame(short rx,short cx)
- {
- register short n,r,c,r1,c1,r2,c2;
- unsigned long x;
-
- for (r = 0; r < rows; r++)
- for (c = 0; c < cols; c++)
- minefield(r,c) = 0;
-
- minefield(rx,cx) = kFlag; // flag the original click cell
- n = mines;
- while (0 < n) {
- x = Random();
- r1 = x & 0x7FFF;
- r = r1 % rows;
- r1 = (x >> 8) & 0x7FFF;
- c = r1 % cols;
- if ((minefield(r,c) & (~kNumMask)) == 0) {
- minefield(r,c) = kMine;
- r1 = (r == 0) ? 0 : r - 1;
- r2 = (r >= rows - 1) ? rows - 1 : r + 1;
- for ( ; r1 <= r2; r1++) {
- c1 = (c == 0) ? 0 : c - 1;
- c2 = (c >= cols - 1) ? cols - 1 : c + 1;
- for ( ; c1 <= c2; c1++) {
- if (minefield(r1,c1) != kMine)
- minefield(r1,c1)++;
- }
- }
- n--;
- }
- }
- minefield(rx,cx) -= kFlag; // unflag the original click cell
-
- GetDateTime(&gStartTime); // start timing the game now
- now = gStartTime;
- gNewGame = false;
- gRunning = true;
- }
-
- void
- GameTime(void)
- {
- if (gRunning) {
- GetDateTime(&now);
- if (now != then) {
- SetPort(gMineWindow);
- InvalRect(&gHdrRect);
- }
- }
- }
- void
- DrawGame(BitMap *pixMap)
- {
- if (gNewGame)
- DrawNewMap(pixMap);
- else
- DrawHdr();
- }
-
- unsigned char
- minechar(short r,short c)
- {
- short v;
-
- v = minefield(r,c);
- return ((v >= kMine) ? kBombPict: (v & kNumMask) + kNumPict);
- }
-
- void
- DrawPict(short id,short *x,short *y)
- {
- PicHandle pict;
- Rect box;
-
- if (pict = gPicts[id]) {
- SetRect(&box,*x,*y,*x + (*pict)->picFrame.right,*y + (*pict)->picFrame.bottom);
- DrawPicture(pict,&box);
- *x += (*pict)->picFrame.right;
- }
- }
-
- void
- DrawLCD(short n,short x,short y)
- {
- short i,j;
- unsigned char v;
- Str255 text;
-
- NumToString(n,&text);
- for (i = 0; i < 3; i++) {
- j = text[0] + i - 2;
- v = (j > 0) ? text[j] - '0' : 0;
- DrawPict(v + kLCDPict,&x,&y);
- }
- }
-
- void
- DrawBevel(Rect *box,short width,RGBColor *topColor,RGBColor *bottomColor)
- {
- register short i,a,b1,b2;
-
- RGBForeColor(topColor);
- PenSize(width,width);
- FrameRect(box);
- RGBForeColor(bottomColor);
- PenNormal();
- a = box->bottom-1;
- b1 = box->left;
- b2 = box->right-1;
- for (i = 0; i < width; i++) {
- MoveTo(b1++,a);
- LineTo(b2--,a--);
- }
- a = box->right-1;
- b1 = box->top;
- b2 = box->bottom-1;
- for (i = 0; i < width; i++) {
- MoveTo(a,b1++);
- LineTo(a--,b2--);
- }
- }
-
- void
- DrawFrame(void)
- {
- short x,y;
- Rect box,box1;
-
- box = gMineWindow->portRect;
- box.top = kBorderTop; // Header & menu bar
- RGBForeColor(&gLtGray);
- PaintRect(&box);
-
- DrawBevel(&box,kBorder1,&gWhite,&gDkGray);
-
- InsetRect(&box,kBorder1+kBorder2,kBorder1+kBorder2);
- box1 = box;
- box1.bottom = box1.top + 2*kBorderLCD + +2* kBorder3h + kHeightLCD;
- DrawBevel(&box1,kBorder3h,&gDkGray,&gWhite);
-
- box1 = box;
- box1.top = kHdrSize - kBorder3;
- DrawBevel(&box1,kBorder3,&gDkGray,&gWhite);
-
- RGBForeColor(&gDkGray);
- x = kInsetLCD;
- y = kBorderTop + kInsetLCD + kHeightLCD - 1;
- MoveTo(x,kBorderTop + kInsetLCD);
- LineTo(x,y);
- RGBForeColor(&gWhite);
- x += 3*kWidthLCD + 1;
- MoveTo(x,kBorderTop + kInsetLCD);
- LineTo(x,y);
- RGBForeColor(&gDkGray);
- x = gMineWindow->portRect.right - kInsetLCD - 3*kWidthLCD - 2;
- MoveTo(x,kBorderTop + kInsetLCD);
- LineTo(x,y);
- RGBForeColor(&gWhite);
- x += 3*kWidthLCD + 1;
- MoveTo(x,kBorderTop + kInsetLCD);
- LineTo(x,y);
- RGBForeColor(&gBlack);
- }
-
- void
- DrawHdr(void)
- {
- DrawCell(gFace,&gFaceRect);
-
- DrawLCD(mines,kInsetLCD + 1,kBorderTop + kInsetLCD);
-
- GetDateTime(&now);
- DrawLCD(now - gStartTime,gMineWindow->portRect.right - kInsetLCD - 3*kWidthLCD - 1,
- kBorderTop + kInsetLCD);
- then = now;
- }
-
- void
- DrawCell(short id,Rect *box)
- {
- PicHandle pict;
-
- if (pict = gPicts[id])
- DrawPicture(pict,box);
- }
-
- void
- DrawNewMap(BitMap *pixMap)
- {
- short r,c;
- Rect box,box1;
-
- DrawFrame();
- DrawHdr();
- SetRect(&box,kBorder,kHdrSize,kBorder+kBox,kHdrSize+kBox);
- r = 0;
- for (c = 0; c < cols; c++) {
- DrawCell(mineview(r,c),&box);
- box.left += kBox;
- box.right += kBox;
- }
- box.left = kBorder;
- box.right -= kBox;
- gGameRect = box;
- for (r = 1; r < rows; r++) {
- box1 = box;
- box.top += kBox;
- box.bottom += kBox;
- CopyBits(pixMap,pixMap,&box1,&box,srcCopy,nil);
- }
- gGameRect.bottom = box.bottom;
- }
-
- void
- DrawMap(void)
- {
- short r,c;
- Rect box;
-
- DrawHdr();
- SetRect(&box,kBorder,kHdrSize,kBorder+kBox,kHdrSize+kBox);
- for (r = 0; r < rows; r++) {
- box.left = kBorder;
- box.right = box.left + kBox;
- for (c = 0; c < cols; c++) {
- DrawCell(mineview(r,c),&box);
- box.left += kBox;
- box.right += kBox;
- }
- box.top += kBox;
- box.bottom += kBox;
- }
- }
-
- void
- ClickMines(void)
- {
- short r,c,x,y;
- unsigned char v,v1;
- Rect box;
-
- for (r = 0; r < rows; r++) {
- for (c = 0; c < cols; c++) {
- v = minechar(r,c);
- if (v == kBombPict)
- v1 = v;
- else
- if (mineview(r,c) == kFlagPict) // misidentified
- v1 = kBadPict;
- else
- v1 = 0;
- if (v1 != 0) {
- mineview(r,c) = v1;
- x = c * kBox + kBorder;
- y = r * kBox + kHdrSize;
- SetRect(&box,x,y,x + kBox,y + kBox);
- DrawCell(v1,&box);
- }
- }
- }
- gFace = kSadFace;
- gEndGame = true;
- }
-
- void
- ClickNeighbors(r,c)
- {
- short r1,c1,r2,c2,x,y;
- unsigned char v;
- Rect box;
-
- r1 = (r == 0) ? 0 : r - 1;
- r2 = (r >= rows - 1) ? rows - 1 : r + 1;
- for ( ; r1 <= r2; r1++) {
- c1 = (c == 0) ? 0 : c - 1;
- c2 = (c >= cols - 1) ? cols - 1 : c + 1;
- for ( ; c1 <= c2; c1++) {
- v = minechar(r1,c1);
- if (mineview(r1,c1) == kButtonPict) { // currently unturned or unflagged
- mineview(r1,c1) = v;
- x = c1 * kBox + kBorder;
- y = r1 * kBox + kHdrSize;
- SetRect(&box,x,y,x + kBox,y + kBox);
- DrawCell(v,&box);
- if (v == kNumPict)
- ClickNeighbors(r1,c1);
- }
- }
- }
- }
-
- Boolean PtInGame(Point where)
- {
- return (PtInRect(where,&gGameRect) || PtInRect(where,&gFaceRect));
- }
-
- void
- ClickGame(Point where,short modifiers)
- {
- Boolean result = false;
-
- reclick:
- while (StillDown()) {
- GetMouse(&where);
- if (PtInRect(where,&gGameRect) && (!gEndGame))
- ClickCell(where,modifiers);
- else
- if (PtInRect(where,&gFaceRect)) {
- DrawCell(kPressedFace,&gFaceRect);
- while (StillDown()) {
- GetMouse(&where);
- if (!PtInRect(where,&gFaceRect)) { // dragged out of the box
- DrawCell(gFace,&gFaceRect);
- goto reclick; // try again
- }
- }
- NewGame(false);
- }
- }
- }
-
- void
- ClickCell(Point where,short modifiers)
- {
- unsigned char v;
- short r,c,x,y;
- Rect box;
-
- DrawCell(kOwFace,&gFaceRect);
- where.h -= kBorder;
- where.v -= kHdrSize;
- r = where.v / kBox;
- c = where.h / kBox;
- x = c * kBox + kBorder;
- y = r * kBox + kHdrSize;
- SetRect(&box,x,y,x + kBox,y + kBox);
- if (mineview(r,c) == kButtonPict)
- DrawCell(kEmptyPict,&box);
- while (StillDown()) {
- GetMouse(&where);
- if (!PtInRect(where,&box)) { // dragged out of the box
- if (mineview(r,c) == kButtonPict)
- DrawCell(kButtonPict,&box);
- if (!PtInRect(where,&gGameRect)) // dragged out of the game
- DrawCell(gFace,&gFaceRect);
- return; // try new box
- }
- }
- if (gNewGame)
- InitGame(r,c);
- if (mineview(r,c) == kMarkPict) { // was a mark flag
- v = kButtonPict;
- } else
- if (mineview(r,c) == kFlagPict) { // was a bomb flag
- mines++;
- v = (gMarks) ? kMarkPict : kButtonPict;
- } else
- if (modifiers) { // any modifier key down
- v = kFlagPict;
- mines--;
- } else { // just a clean click
- v = minechar(r,c);
- if (v == kBombPict) {
- if (gSound) SysBeep(4);
- ClickMines();
- v = kBoomPict; // we blew up
- }
- }
- mineview(r,c) = v;
- DrawCell(v,&box);
- if (v == kNumPict) // this cell has no surrounding bombs
- ClickNeighbors(r,c);
- DrawHdr();
- SaveBits(gMineWindow);
- gRunning = (mines != 0);
- }
-
-